#include "AST_TestSuites.h"


// AST component testing...


// AST core tests..
void SIMPLE::AST_coreTest::setUp () {
	this->_ast = new AST();
};
void SIMPLE::AST_coreTest::tearDown () {
	if( this->_ast != NULL );
	delete _ast;
};

void SIMPLE::AST_coreTest::Test_Constructor () {
	CPPUNIT_ASSERT( !(this->_ast == NULL) );
};


void SIMPLE::AST_coreTest_New_statement::setUp () {
	this->_ast = new AST();
	this->p1	= new procNode(1);
	this->p2	= new procNode(2);
	this->e1_const_1	= new numeric_expr (1);
	this->e2_const_2	= new numeric_expr (2);
	this->e3_var_x_3	= new numeric_expr (3);
	this->e4_var_y_4	= new numeric_expr (4);
	this->e7_plus		= new composite_expr (OP_Plus );
	this->e8_minus		= new composite_expr (OP_Minus );
	this->e9_times		= new composite_expr (OP_Times );

	this->_asn_1 = new assignment_stmtNode (p1->_procedure_id, e3_var_x_3->_expr_id, 1 );
	this->_asn_1->setRHS ( e1_const_1 );
	this->c_proc1 = new call_stmtNode(2, 1, p1->_procedure_id );
	this->w_var_x = new while_stmtNode(3, e3_var_x_3->_expr_id, p1->_procedure_id );
	this->_asn_2 = new assignment_stmtNode( 4, e3_var_x_3->_expr_id, p1->_procedure_id );
	this->_asn_2->setRHS ( e2_const_2 );


};

void SIMPLE::AST_coreTest_New_statement::tearDown () {
	delete this->_ast;
	delete this->p1;
	delete this->p2;
	delete this->e1_const_1;
	delete this->e2_const_2;
	delete this->e3_var_x_3;
	delete this->e4_var_y_4;
	delete this->e7_plus;
	delete this->e8_minus;
	delete this->e9_times;

	delete this->_asn_1;
	delete this->c_proc1;
	delete this->w_var_x;
	delete this->_asn_2;
};
void SIMPLE::AST_coreTest_New_statement::Test_Add_Get_NewStmt() {
	CPPUNIT_ASSERT_EQUAL_MESSAGE( "[assertion 1] NO procedures in AST => should return 0 for num of procedures ", 
		0, _ast->numProcs() );
		CPPUNIT_ASSERT_EQUAL_MESSAGE( "[assertion 2] NO statements in AST => should return 0 for num of Statements ", 
		0, _ast->numStmts() );
	this->_ast->addNewProcedure(p1);
	CPPUNIT_ASSERT_EQUAL_MESSAGE( "[assertion 3] first procedure addition => should return 1 for num of procedures ", 
		1, _ast->numProcs() );

	_asn_1->_stmtIndex = 1; _asn_1->_proc_id = 1;
	_ast->addStmt( _asn_1 );
	CPPUNIT_ASSERT_EQUAL_MESSAGE( "[assertion 4] first statement addition in proc-id-1 => num of statements = 1", 
		1, _ast->numStmts() );

	_ast->addStmt( c_proc1 );
	CPPUNIT_ASSERT_EQUAL_MESSAGE( "[assertion 5] second statement addition in proc-id-1 => num of statements = 2", 
		2, _ast->numStmts() );

	_ast->addNewProcedure(p2);
	CPPUNIT_ASSERT_EQUAL_MESSAGE( "[assertion 6] secand procedure addition => should return 2 for num of procedures ", 
		2, _ast->numProcs() );

};

// 
void SIMPLE::AST_coreTest_Statement_AcrossProcedures::Test_Add_Get_Stmts_AcrossProcedures () {
};

// Assign Statements node data tests
void SIMPLE::AssignStmt_Data_Test::setUp() {
	e1_const_1 = new numeric_expr(1);
	e2_const_2 = new numeric_expr(2);

	e3_var_x_1 = new numeric_expr(1);
	e4_var_y_2 = new numeric_expr(2);
	e5_var_z_3 = new numeric_expr(3);
	e6_var_a_4 = new numeric_expr(4);

	e7_plus = new composite_expr(OP_TYPE::OP_Plus);

	e8_minus = new composite_expr(OP_TYPE::OP_Minus);
	e9_times = new composite_expr(OP_TYPE::OP_Times);

	// (1)x=1
	this->_asn_1_1 = new assignment_stmtNode(1, 1, 1);
	this->_asn_1_1->setLHS(e3_var_x_1);
	this->_asn_1_1->setRHS(e1_const_1);

	// (2)x=x-1
	this->_asn_1_2 = new assignment_stmtNode( 2, e3_var_x_1->_expr_id , 1 );
	this->_asn_1_2->setLHS (e3_var_x_1 );
	composite_expr *e = new composite_expr(OP_TYPE::OP_Plus);
	e->setLHS( e3_var_x_1 );
	e->setRHS( e1_const_1 );
	this->_asn_1_2->setRHS (e);


	// (3)y=x*1
	this->_asn_2_3 = new assignment_stmtNode( 3, e4_var_y_2->_expr_id , 2 );

	// (4)y=y+x
	this->_asn_2_4 = new assignment_stmtNode( 4, e4_var_y_2->_expr_id , 2 );

};
void SIMPLE::AssignStmt_Data_Test::tearDown () {
	delete this->_asn_1_1;
	delete this->_asn_1_2;
	delete this->_asn_2_3;
};
void SIMPLE::AssignStmt_Data_Test::Test_Constructor () {
	CPPUNIT_ASSERT ( _asn_1_1 != NULL);
	CPPUNIT_ASSERT ( _asn_1_1->stmtType == STATEMENT_TYPE::STATEMENT_Assign);
	CPPUNIT_ASSERT ( _asn_1_1->stmtType != STATEMENT_TYPE::STATEMENT_Call);
	CPPUNIT_ASSERT ( _asn_1_1->stmtType != STATEMENT_TYPE::STATEMENT_While);
	CPPUNIT_ASSERT ( _asn_1_1->stmtType != STATEMENT_TYPE::STATEMENT_If);
	CPPUNIT_ASSERT ( _asn_1_1->_stmtIndex == 1 );
	CPPUNIT_ASSERT ( _asn_1_1->_proc_id == 1 );
};
void SIMPLE::AssignStmt_Data_Test::Test_SetAndGet () {
	// (1)x=1
	CPPUNIT_ASSERT_EQUAL ( this->_asn_1_1->getLHS()->_expr_id, 1 );
	CPPUNIT_ASSERT_EQUAL ( this->_asn_1_1->getRHS()->_expr_id, 1 );

	// (2)x=x-1
	CPPUNIT_ASSERT_EQUAL ( this->_asn_1_2->getLHS()->_expr_id, e3_var_x_1->_expr_id );
	CPPUNIT_ASSERT_EQUAL ( this->_asn_1_2->getRHS()->toString(), e7_plus->toString() );

	string invalid_string = "*";
	CPPUNIT_ASSERT_ASSERTION_FAIL ( 
		CPPUNIT_ASSERT_EQUAL ( this->_asn_1_2->getRHS()->toString(), invalid_string) );
	CPPUNIT_ASSERT_ASSERTION_FAIL ( 
		CPPUNIT_ASSERT_EQUAL ( this->_asn_1_2->getLHS()->toString(), invalid_string) );

	// (3)y=x*1
	// not implemented...

	// (4)y=y+x
	// not implemented...

};


// call statement node data tests
void SIMPLE::CallStmt_Data_Test::setUp () {
	this->c_1_proc1_3 = new call_stmtNode (1, 1, 3 );
	this->c_2_proc2_4 = new call_stmtNode (2, 2, 4 );
};
void SIMPLE::CallStmt_Data_Test::tearDown () {
	delete c_1_proc1_3;
	delete c_2_proc2_4;
};
void SIMPLE::CallStmt_Data_Test::Test_Constructor () {
	CPPUNIT_ASSERT_EQUAL ( c_1_proc1_3->getStmtIndex(), 1 );
	CPPUNIT_ASSERT_EQUAL ( c_1_proc1_3->getStmtType() , STATEMENT_TYPE::STATEMENT_Call );
	CPPUNIT_ASSERT_EQUAL ( c_1_proc1_3->_proc_id, 3 );

	CPPUNIT_ASSERT_EQUAL ( c_2_proc2_4->getStmtIndex(), 2 );
	CPPUNIT_ASSERT_EQUAL ( c_2_proc2_4->getStmtType() , STATEMENT_TYPE::STATEMENT_Call );
	CPPUNIT_ASSERT_EQUAL ( c_2_proc2_4->_proc_id, 4 );

};
void SIMPLE::CallStmt_Data_Test::Test_SetAndGet () {
	CPPUNIT_ASSERT_EQUAL ( c_1_proc1_3->getCallProcID(), 1 );
	CPPUNIT_ASSERT_EQUAL ( c_2_proc2_4->getCallProcID(), 2 );

	CPPUNIT_ASSERT_ASSERTION_FAIL ( 
		CPPUNIT_ASSERT_EQUAL ( c_1_proc1_3->getCallProcID(), 2 ) );
	CPPUNIT_ASSERT_ASSERTION_FAIL ( 
		CPPUNIT_ASSERT_EQUAL ( c_2_proc2_4->getCallProcID(), 1 ) );
};


// While Statements node data tests
void SIMPLE::WhileStmt_Test::setUp () {
	w_1_conditionVarId_1_proc_1 = new while_stmtNode( 1, 1, 1 );
	w_2_conditionVarId_1_proc_2 = new while_stmtNode( 2, 1, 2 );
	w_3_conditionVarId_2_proc_2 = new while_stmtNode( 3, 2, 2 );
	w_4_conditionVarId_3_proc_1 = new while_stmtNode( 4, 3, 1 );
};
void SIMPLE::WhileStmt_Test::tearDown () {
	delete w_1_conditionVarId_1_proc_1;
	delete w_2_conditionVarId_1_proc_2;
	delete w_3_conditionVarId_2_proc_2;
	delete w_4_conditionVarId_3_proc_1;
};
void SIMPLE::WhileStmt_Test::Test_Constructor () {
	CPPUNIT_ASSERT_EQUAL ( w_1_conditionVarId_1_proc_1->getStmtIndex(), 1 );
	CPPUNIT_ASSERT_EQUAL ( w_2_conditionVarId_1_proc_2->getStmtIndex(), 2 );
	CPPUNIT_ASSERT_EQUAL ( w_3_conditionVarId_2_proc_2->getStmtIndex(), 3 );
	CPPUNIT_ASSERT_EQUAL ( w_4_conditionVarId_3_proc_1->getStmtIndex(), 4 );

	CPPUNIT_ASSERT_EQUAL ( w_1_conditionVarId_1_proc_1->getStmtType(), STATEMENT_TYPE::STATEMENT_While );
	CPPUNIT_ASSERT_EQUAL ( w_2_conditionVarId_1_proc_2->getStmtType(), STATEMENT_TYPE::STATEMENT_While );
	CPPUNIT_ASSERT_EQUAL ( w_3_conditionVarId_2_proc_2->getStmtType(), STATEMENT_TYPE::STATEMENT_While );
	CPPUNIT_ASSERT_EQUAL ( w_4_conditionVarId_3_proc_1->getStmtType(), STATEMENT_TYPE::STATEMENT_While );

	CPPUNIT_ASSERT_EQUAL ( w_1_conditionVarId_1_proc_1->getConditionVar(), 1 );
	CPPUNIT_ASSERT_EQUAL ( w_3_conditionVarId_2_proc_2->getConditionVar(), 2 );
	CPPUNIT_ASSERT_EQUAL ( w_2_conditionVarId_1_proc_2->getConditionVar(), 1 );

	CPPUNIT_ASSERT_ASSERTION_FAIL( 
		CPPUNIT_ASSERT_EQUAL ( w_1_conditionVarId_1_proc_1->getStmtType(), STATEMENT_TYPE::STATEMENT_Assign ) );
	CPPUNIT_ASSERT_ASSERTION_FAIL( 
		CPPUNIT_ASSERT_EQUAL ( w_2_conditionVarId_1_proc_2->getStmtType(), STATEMENT_TYPE::STATEMENT_Call ) );
	CPPUNIT_ASSERT_ASSERTION_FAIL( 
		CPPUNIT_ASSERT_EQUAL ( w_1_conditionVarId_1_proc_1->getStmtIndex(), 2 ) );
	CPPUNIT_ASSERT_ASSERTION_FAIL( 
		CPPUNIT_ASSERT_EQUAL ( w_1_conditionVarId_1_proc_1->getConditionVar(), 2 ) );
	CPPUNIT_ASSERT_ASSERTION_FAIL( 
		CPPUNIT_ASSERT_EQUAL ( w_3_conditionVarId_2_proc_2->getConditionVar(), 1 ) );


};


// If Statements node data tests
void SIMPLE::IfStmt_Test::setUp (){
	if_1_conditionVarId_1_proc_1 = new if_stmtNode( 1, 1, 1 );
	if_2_conditionVarId_1_proc_1 = new if_stmtNode( 2, 1, 1 );
	if_3_conditionVarId_4_proc_2 = new if_stmtNode( 3, 4, 2 );
	if_4_conditionVarId_5_proc_2 = new if_stmtNode( 4, 5, 2 );
};
void SIMPLE::IfStmt_Test::tearDown (){
	delete if_1_conditionVarId_1_proc_1;
	delete if_2_conditionVarId_1_proc_1;
	delete if_3_conditionVarId_4_proc_2;
	delete if_4_conditionVarId_5_proc_2;
};

void SIMPLE::IfStmt_Test::Test_Constructor (){
	CPPUNIT_ASSERT_EQUAL (if_1_conditionVarId_1_proc_1->getStmtIndex(), 1);
	CPPUNIT_ASSERT_EQUAL (if_1_conditionVarId_1_proc_1->getStmtType(), STATEMENT_TYPE::STATEMENT_If );
	CPPUNIT_ASSERT_EQUAL (if_1_conditionVarId_1_proc_1->_proc_id, 1 );
	CPPUNIT_ASSERT_EQUAL (if_1_conditionVarId_1_proc_1->getConditionVar(), 1 );

	CPPUNIT_ASSERT_EQUAL (if_2_conditionVarId_1_proc_1->getStmtIndex(), 2);
	CPPUNIT_ASSERT_EQUAL (if_2_conditionVarId_1_proc_1->getStmtType(), STATEMENT_TYPE::STATEMENT_If );
	CPPUNIT_ASSERT_EQUAL (if_2_conditionVarId_1_proc_1->getConditionVar(), 1);

	CPPUNIT_ASSERT_EQUAL (if_3_conditionVarId_4_proc_2->_proc_id, 2);
	CPPUNIT_ASSERT_EQUAL (if_3_conditionVarId_4_proc_2->getConditionVar(), 4);

	CPPUNIT_ASSERT_EQUAL (if_4_conditionVarId_5_proc_2->getConditionVar(), 5);

	CPPUNIT_ASSERT_ASSERTION_FAIL (
		CPPUNIT_ASSERT_EQUAL ( if_1_conditionVarId_1_proc_1->getStmtIndex(), 2 ) );
	CPPUNIT_ASSERT_ASSERTION_FAIL (
		CPPUNIT_ASSERT_EQUAL ( if_1_conditionVarId_1_proc_1->getConditionVar(), 2 ) );
	CPPUNIT_ASSERT_ASSERTION_FAIL (
		CPPUNIT_ASSERT_EQUAL ( if_1_conditionVarId_1_proc_1->getStmtType(), STATEMENT_TYPE::STATEMENT_Call) );
	CPPUNIT_ASSERT_ASSERTION_FAIL (
		CPPUNIT_ASSERT_EQUAL ( if_2_conditionVarId_1_proc_1->getStmtIndex(), 1 ) );
	CPPUNIT_ASSERT_ASSERTION_FAIL (
		CPPUNIT_ASSERT_EQUAL ( if_3_conditionVarId_4_proc_2->getConditionVar(), 2 ) );
	CPPUNIT_ASSERT_ASSERTION_FAIL (
		CPPUNIT_ASSERT_EQUAL ( if_2_conditionVarId_1_proc_1->_proc_id, 2 ) );


};